package flex01;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;

import modle.Player;
import modle.Table;
import servlet.StartSocketServlet;
/**
 * @描述 用于处理和客户端的交互线程。每连接一个用户，就开启一个线程。
 * @author 高通
 *@modify 2012/12/20
 */
public class SocketThread implements Runnable {
	
	public static final String START_GAME = "startGame";
	public static final String GAME = "game";
	public static final String ALL_READY = "allReady";
	public static final String ESCAPE = "escape";
	public static final String LOOKERIN = "lookerin";
	public static final String GAMECHAT = "gamechat";
	public static final String SETUPGAME = "setupGame";
	
	public static final int WAITING = 1;
	public static final int PLAYER_READY = 2;
	public static final int GAMING = 3;
	public static final int LOOKING = 4;
	
	private Socket socket;
	private String encoding;
	private SocketServer server;
	Player player = new Player();
	//Table table = new Table();
	public static int cnt = 0;
	String getMsg;
	public SocketThread(Socket socket,String encoding,SocketServer server) {
		this.socket = socket;
		this.encoding = encoding;
		this.server = server;
	}
	
	/**
	 * 与客户端交互代码
	 */
	public void run() {
		BufferedReader br = null;
		BufferedWriter bw = null;
		try {
			br = new BufferedReader(new InputStreamReader(socket
					.getInputStream(), encoding));
			bw = new BufferedWriter(new OutputStreamWriter(
					socket.getOutputStream(), encoding));
			cnt ++;
			
			while ((getMsg = br.readLine()) != null && !"exit".equalsIgnoreCase(getMsg)) {
				
				String strArr[] = getMsg.split("\\$");
				String cmd = strArr[0];
				System.out.println("服务器收到消息："+strArr[0]);
				//如果有新的用户进入房间
				if(cmd.equals(SocketServer.NEW_PLAYER)){  //字符串格式为 <cmd> <name>
					int roomIndex = StartSocketServlet.socketServerList.indexOf(server);
					//首先把该用户放入clientList列表
					player.setSocket(socket);
					player.setTablePosition(-1);
					player.setName(strArr[1]);
					server.clientList.add(player);
					
					//再向所有房间 所有用户发送广播
					SocketServer.sendMessage2AllRooms(getMsg + "$" + server.clientList.size()+"$" + roomIndex +"\r\n");
					System.out.println(getMsg + "$" + server.clientList.size()+ "\r\n");
				}else if(cmd.equals(SocketServer.GAMEIN1)){  //处理玩家1进入. 说明 增加一局游戏
					
					gameIn1(Integer.parseInt(strArr[2]));
				}
				else if(cmd.equals(SocketServer.GAMEIN2)){
					
					int tableIndex = Integer.parseInt(strArr[2]);
					gameIn2(tableIndex);
				}
				else if(cmd.equals(SocketServer.ADDTABLE)){
					
					Table table = new Table();
					table.setPlayer1(player.getName());  //由于一个线程对应一个用户，我可以直接拿到用户的名字8
					table.setIndex(server.tableMap.size());
					table.setName(strArr[2]);
					
					server.tableMap.put(server.tableMap.size(), table);
					
					player.setSocket(socket);
					player.setTablePosition( (server.tableMap.size()-1) *2);
					
					server.sendMessage2All(getMsg + "$" + (server.clientList.size()-1));
					
					System.out.println("add table:"+getMsg + "$" + (server.clientList.size()-1));
					
				}
				else if(cmd.equals(SocketServer.GAMEOUT1)){
					int tableIndex = Integer.parseInt(strArr[2]);
					gameOut1(tableIndex,true);
				}else if(cmd.equals(SocketServer.GAMEOUT2)){
					int tableIndex = Integer.parseInt(strArr[2]);
					gameOut2(tableIndex,true);
				}
				else if(cmd.equals(SocketServer.TABLECHG)){
					int oldIndex = Integer.parseInt(strArr[3]);
					int newIndex = Integer.parseInt(strArr[5]); //得到切换后房间的index

					if(strArr[1].equals(SocketServer.GAMEOUT1))
						gameOut1(oldIndex,false);
					else
						gameOut2(oldIndex,false);
					
					if(strArr[4].equals(SocketServer.GAMEIN1))
						gameIn1(newIndex);
					else
						gameIn2(newIndex);

				}else if(cmd.equals(SocketServer.GAMEOUT)){ //当前玩家退出
					
				}
				else if(cmd.equals(SocketServer.ROOMCHAT)){
					server.sendMessage2All(getMsg + "$" + player.getName());
				}
				else if(cmd.equals(LOOKERIN)){ //消息是 旁观者进入
					int tableIndex = Integer.parseInt(strArr[1]);
					
					//在玩家列表 进入本玩家
					Table table = server.tableMap.get(tableIndex);
					table.players.add(player);
					
					player.setTablePosition(tableIndex*2);
					player.state = LOOKING;
					
					
					//想本桌玩家发送信息，有玩家旁观
					server.send2Table(table, getMsg + "$" + player.getName());
					
					
				}else if(cmd.equals(ESCAPE)){ //这个是在玩家点击点击退出游戏时，发送的消息。和直接关闭浏览器不同！
					
				}
				else if(cmd.equals("game")){
					gameManage(strArr);
				}
				
				bw.flush();
			}
			
			
			
			cnt --;
			
			//连接关闭后，从客户端列表中删除 该连接
			//player.setTablePosition(-1);
			sockeClose(br, bw);
			
			
		} catch (Exception e) {
			try {
				sockeClose(br,bw);
			} catch (IOException e2) {
				e2.printStackTrace();
			}
			if(!socket.isClosed()){
				try {
					socket.close();
				} catch (IOException e1) {
					e1.printStackTrace();
				}
			}
			
			e.printStackTrace();
			//throw new RuntimeException("Socket线程类发送异常...",e);
		}
	}

	

	private void sockeClose(BufferedReader br, BufferedWriter bw)
			throws IOException {
		server.clientList.remove(player);
		
		System.out.println("当前Socket连接结束...... 删除玩家,剩余人数："+server.clientList.size());
		//通知所有房间的  所有客户端，有玩家退出
		int roomIndex = StartSocketServlet.socketServerList.indexOf(server); //得到服务器的序号，即房间号
		
		//先得到用户的位置
		int position = player.getTablePosition();
		int tableIndex = position/2;
		
		if(position < 0){ //说明用户没有坐下，在房间闲逛
			//String msg = SocketServer.ROOMOUT; //直接更新人员列表就行了
			server.sendMessage2All(SocketServer.ROOMOUT);
		}else{
			
			Table table = server.tableMap.get(tableIndex);
			
			//如果玩家在游戏中，则发生 玩家逃跑的消息
			if(GAMING == player.state ){
				int pos = position%2;
				table.players.set(pos,null);//更新玩家列表
				
				if(pos == 0){
					table.player1 = ""; 
					table.players.get(1).state = WAITING; //把另一个玩家的状态设置为等待！
				}
				else{
					table.player2 = "";
					table.players.get(0).state = WAITING; //把另一个玩家的状态设置为等待！
				}
					
				table.players.set(pos, null);
				
				server.sendMessage2All(ESCAPE + "$" + tableIndex + "$" + (pos+1));
				
			}else{
				if(position%2 == 0){  //用户为player1
					if(table.getPlayer2() == ""){
						System.out.println("exit removeTable"+"$"+ tableIndex);
						if(server.type == 'D') ////如果桌子是动态的，用户在退出房间后，还要删除桌子，静态的则不管
							server.sendMessage2All("removeTable"+"$"+ tableIndex + "$" + "roomout");
						else //静态
							server.sendMessage2All(SocketServer.GAMEOUT1 + "$"+ player.getName() + "$" + tableIndex + "$" + "roomout");

						server.tableMap.remove(tableIndex);
					}else{
						System.out.println("GAMEOUT1:" + server.tableMap.size());
						//清空table中palyer1的位置
						server.tableMap.get(tableIndex).setPlayer1("");
						server.sendMessage2All(SocketServer.GAMEOUT1 + "$"+ player.getName() + "$" + tableIndex + "$" + "roomout");
					}
				}
				else{
					if(table.getPlayer1() == ""){
						System.out.println("exit removeTable"+"$"+ tableIndex);
						
						if(server.type == 'D') ////如果桌子是动态的，用户在退出房间后，还要删除桌子，静态的则不管
							server.sendMessage2All("removeTable"+"$"+ tableIndex + "$" + "roomout");
						else
							server.sendMessage2All(SocketServer.GAMEOUT2 + "$"+ player.getName() + "$" + tableIndex + "$" + "roomout");
						
						server.tableMap.remove(tableIndex);
					}else{
						System.out.println("GAMEOUT2 kkk:" + server.tableMap.size());
						
						server.tableMap.get(tableIndex).setPlayer2("");
						server.sendMessage2All(SocketServer.GAMEOUT2 + "$"+ player.getName() + "$" + tableIndex + "$" + "roomout");
					}
				}
			}			
			
			//判断玩家是否在游戏中
			
		}
		
		//最后给其它房间的用户，发送广播
		server.send2AllNoMyRoom(SocketServer.PLAYEREXIT+ "$" + player.getTablePosition() + "$" + server.clientList.size() + "$" + roomIndex);
		System.out.println(server.getPort()+"  当前连接数："+ server.clientList.size());
		
		br.close();
		bw.close();
		socket.close();
	}
	
	private void gameIn2(int tableIndex) {
		
		//int tableIndex = Integer.parseInt(strArr[2]);
		player.setTablePosition(tableIndex*2+1);      //更新 位置
		server.sendMessage2All(getMsg);
		
		//player2进入，说明table应该是不为空的
		Table table = server.tableMap.get(tableIndex);
		if(table != null){
			table.setPlayer2(player.getName());
		}
		else{
			table = new Table();
			table.setIndex(tableIndex);
			table.setPlayer2(player.getName());
		}
		
		server.tableMap.put(tableIndex, table);
		
		//假设一切正常，是第2个玩家进入
		if(table.players.size() == 1)
			table.players.add(player);
		else{
			table.players.set(1,player);
		}
		
		System.out.println(getMsg);
	}

	private void gameIn1(int tableIndex){
		//int tableIndex = Integer.parseInt(strArr[2]);
		
		player.setTablePosition(tableIndex*2);   //更新
		
		//构建一个新的table 存入map
		Table table = server.tableMap.get(tableIndex);
		if(table == null)
			table = new Table();
		table.setIndex(tableIndex);
		
		//判断信息延迟问题！  如果有其它用户抢先一步
		if(table.getPlayer1() != ""){
			
			if(table.getPlayer2() == ""){
				//此时，用户坐下的其实是player2的位置
				player.setTablePosition(tableIndex*2+1);
				//服务器发回的信息应该是 GAMEIN2
				server.sendMessage2All(SocketServer.GAMEIN2 + "$" + player.getName() + "$" + tableIndex);
				
			}else{
				server.sendToClient(player.getSocket(), "roomAll");
			}
			
		}else{ //否则 一切正常
			table.setPlayer1(player.getName());
			server.sendMessage2All(getMsg);
			
			//本桌子玩家列表， 增加本用户
			if(table.players.size() == 0)
				table.players.add(player);
			else
				table.players.set(0, player);
		}
		
		
		server.tableMap.put(tableIndex, table);
		
		
		System.out.println(getMsg);
	}
	
	private void gameOut1(int tableIndex, boolean flag){
		player.setTablePosition(-1);
		//int tableIndex = Integer.parseInt(strArr[2]);
		//由于是第一个玩家退出，需要判断桌子是否有第二个玩家，么有就删除该桌子
		Table table = null;
		if( (table = server.tableMap.get(tableIndex)) != null
				&& table.getPlayer2() == ""){
			System.out.println("server.type:"+server.type+"$"+table.getPlayer2());
				if(server.type == 'D'){
					System.out.println("removeTable"+"$"+ tableIndex);
					server.sendMessage2All("removeTable"+"$"+ tableIndex);//此信息发给，动态房间。删除桌子   
				}else{
					if(flag)
						server.sendMessage2All(getMsg); //此信息发给，静态房间，
				}
					
			//不管静态动态，服务器都要删除桌子
			server.tableMap.remove(tableIndex);
		}
		else{
			server.tableMap.get(tableIndex).setPlayer1("");
			System.out.println("GAMEOUT1:" + server.tableMap.size());
			if(flag)
				server.sendMessage2All(getMsg);
		}
		
		player.state = 0;
		
		System.out.println(getMsg);
	}
	
	private void gameOut2(int tableIndex, boolean flag){
		player.setTablePosition(-1);
		
		Table table = null;

		//由于是第2个玩家退出，需要判断桌子是否有第1个玩家，么有就删除该桌子
		if( (table = server.tableMap.get(tableIndex)) != null
				&& table.getPlayer1() == ""){ //如果 player1 没人，此桌就为空
			if(server.type == 'D'){
				System.out.println("removeTable"+"$"+ tableIndex);
				server.sendMessage2All("removeTable"+"$"+ tableIndex);
			}else{
				if(flag)
					server.sendMessage2All(getMsg);
			}
			
			server.tableMap.remove(tableIndex);
			
		}else{ //如果player1有人  只发送消息
			System.out.println("GAMEOUT2:" + server.tableMap.size());
			
			server.tableMap.get(tableIndex).setPlayer2("");
			if(flag)
				server.sendMessage2All(getMsg);
		}
		
		player.state = 0;
		
		System.out.println(getMsg);
	}
	
	
	/**
	 * 处理游戏中的所有消息
	 * @param strArr 传入的消息数组
	 */
	private void gameManage(String[] strArr) {
		String cmd = strArr[1];
		
		if(cmd.equals(START_GAME)){  //玩家准备
			int tableIndex = Integer.parseInt(strArr[2]);
			int pos = Integer.parseInt(strArr[3]) - 1;
			
			//判断 用户的信息  和 服务器端信息是否同步
			/*  是否有必要判断用户名同步？  */
			if( (tableIndex*2 + pos ) == player.getTablePosition() ){ 
				Table table = server.tableMap.get(tableIndex);
				
				System.out.println("table.players.size():"+table.players.size());
				
				//pos 为0 就得到player1， pos为2就得到player2
				Player player = table.players.get(pos);
				if(player != null){
					//设置玩家的状态
					player.state = PLAYER_READY;
					
					if(table.players.size() >= 2){
						Player anthorPlayer = table.players.get((pos+1)%2);
						//如果两个玩家都准备了
						if(anthorPlayer != null && anthorPlayer.state == PLAYER_READY ){
							//给桌子的所有人发 消息
							server.send2Table(table, GAME + "$" + ALL_READY);
							anthorPlayer.state = GAMING;
							player.state = GAMING;
						}else
							server.send2Table(table, getMsg);
					}
					else{
						//给桌子的所有人发 消息
						server.send2Table(table, getMsg);
					}
					
				}
				else{ //信息 不同步
					
				}
				
			}
			else{
				/**
				 * 如果不同步，作何处理？
				 */
			}
				
		}else if(cmd.equals(GAMECHAT)){  //游戏内聊天
			int tableIndex = player.getTablePosition()/2;
			Table table = server.tableMap.get(tableIndex);
			
			int type = Integer.parseInt(strArr[4]);
			if(type == 1)
				server.send2Table(table, getMsg);
			else{
				server.sendToClient(table.players.get(0).getSocket(), getMsg);
				server.sendToClient(table.players.get(1).getSocket(), getMsg);
			}
		}
		else if(cmd.equals(SETUPGAME)){  //游戏设置选项
			//更新桌子的  地图
			int tableIndex = player.getTablePosition()/2;
			int mapIndex = Integer.parseInt(strArr[2]);
			Table table = server.tableMap.get(tableIndex);
			table.mapIndex = mapIndex;
			
			//给客户端发送  更新地图 消息
			server.send2Table(table, getMsg);
		}
		
	}
	
}
